fix(setup): wrap all claude CLI calls with .claude.json guard (BUG-011)#69
Merged
Merged
Conversation
BUG-004 added Backup-AndRestoreClaudeJson / snapshot_claude_json around
`claude plugin install` only. Upstream truncation bug #59870 fires on every
CLI invocation that goes through deserialize-modify-serialize, including
`claude mcp get`, `claude mcp add`, and `claude plugin list`. Result:
~/.claude/.claude.json keeps getting truncated on each setup-windows.ps1
run, forcing re-authentication everywhere.
Changes:
- setup-linux.sh: relocate snapshot_claude_json / restore_claude_json_if_truncated
ABOVE the MCP registration block; wrap each MCP loop iteration around
`claude mcp get` + `claude mcp add`; wrap the pre-loop `claude plugin list`.
- setup-windows.ps1: wrap each MCP foreach iteration body around `claude mcp get`
+ `claude mcp add` with Backup-AndRestoreClaudeJson scriptblock; wrap the
pre-loop `claude plugin list` invocation.
- Per-call wrap (not per-loop): legitimate `mcp add` size growth never trips
the >50% shrink restore — each call is checked against its own snapshot.
- Windows: separate scriptblocks per CLI call so `continue` keeps unwinding
the outer foreach correctly.
- BUG-004 comment blocks updated to reflect the broader scope.
- bats parity assertions in tests/setup-linux.bats + setup-windows.bats
fail CI if a future call site is added without the guard.
- specs/BUG-011-mcp-loop-claude-json-guard/{proposal,tasks,verification}.md.
Empirical end-to-end confirmation pending until the next clean-machine
setup run; verification.md documents the wrapper-semantics smoke test
($LASTEXITCODE / stdout / closure preserved across `& $Action`).
Co-Authored-By: Claude Opus 4.7 <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
claude plugin installwith the snapshot/restore guard against upstream truncation buganthropics/claude-code#59870. Every other CLI call site (claude mcp get,claude mcp add,claude plugin list) still hits the deserialize-modify-serialize path that truncates~/.claude/.claude.jsonand forces re-authentication in every project.setup-linux.shandsetup-windows.ps1(per-call wrap, not per-loop, so a legitimatemcp addsize increase never trips the >50% shrink restore).Why per-call (not per-loop)
The restore condition is "new size < 50% of snapshot size". Per-loop wrapping would snapshot before iteration 1, then a successful
mcp addin iteration 5 could legitimately grow the file and a malformed write in iteration 8 could still leave it >50% of the original snapshot — masking the truncation. Per-call wrapping snapshots immediately before each CLI invocation and restores against that single call's baseline.Windows scriptblock semantics
Each
claude <cmd>is wrapped in its own narrowly-scopedBackup-AndRestoreClaudeJson -Action { ... }rather than one wrap around the wholeforeachbody. Reason:continueinside a scriptblock invoked via& $Actiondoes NOT continue the OUTER foreach. Per-call wraps preserve control flow.Empirical smoke test (in
specs/BUG-011-mcp-loop-claude-json-guard/verification.md) confirms$LASTEXITCODE, captured stdout, andforeachclosure variables all survive& $Action.Test plan
tests/setup-linux.bats+ 3 new asserts intests/setup-windows.bats.shellcheck --severity=error setup-linux.shclean.pwsh -Command "Invoke-ScriptAnalyzer -Path setup-windows.ps1 -Severity Error"clean.setup-windows.ps1run with a healthy ~75 KB~/.claude/.claude.json— file is unchanged (or restored from snapshot if upstream fires).Spec
specs/BUG-011-mcp-loop-claude-json-guard/{proposal,tasks,verification}.md